/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core;

import java.awt.Point;
import java.util.LinkedList;

/**
 *
 * @author Hapsari
 */
public class PathFinding {
    public Astar A = new Astar();
    private GreedyBF G = new GreedyBF();
    private BreadthFirstSearch B;
    public int opt;     //1=Astar, 2=GreedyBF, 3=BFS
    public Point[] timeMachine;
    public LinkedList <Point> Path = new LinkedList();
    public LinkedList <Point> finalPath = new LinkedList();
    public LinkedList <String> arrayMachine = new LinkedList();
    public LinkedList <Vendor> arrayVendor = new LinkedList();
    
    PathFinding(int _opt)
    {
        opt = _opt;
    }
    
    public void finding(Point start, Point target)
    {
        if (opt == 1)
        {
            if (A.findpath(start.x, start.y, target.x, target.y))
            {
                A.ReadPath(start.x, start.y, target.x, target.y);
                for (int i=0; i<A.pathLength; i++){
                    Path.add(new Point(A.pathBankX[i],A.pathBankY[i]));
                    //System.out.println("Astar Path["+i+"] "+Path.get(i).x+","+Path.get(i).y);
                }
            }
        }
        else if (opt == 2)
        {
            if (G.findpath(start.x, start.y, target.x, target.y))
            {
                G.ReadPath(start.x, start.y, target.x, target.y);
                for (int i=0; i<G.pathLength; i++){
                    Path.add(new Point(G.pathBankX[i],G.pathBankY[i]));
                    //System.out.println("GreedyBF Path["+i+"] "+Path.get(i).x+","+Path.get(i).y);                    
                }
            }
        }
        else
        {
            B = new BreadthFirstSearch(start,target);
            B.BFS(start);
            B.findPath();
            Path.addAll(B.path);
            //for (int i=0; i<Path.size(); i++)
                //System.out.println("BFS Path["+i+"] "+Path.get(i).x+","+Path.get(i).y);                    
        }
    }
    
    public void setArrayMachine (int[] arr){
        boolean found = false;
        arrayMachine.add(new String(""+arr[0]));
        for(int i=1; i<arr.length; i++){
            found = false;
            for(int j=0; j<arrayMachine.size(); j++){
                if(arrayMachine.get(j).equals(""+arr[i])){
                    found = true;
                    break;
                }
            }
            if (found == false){
               arrayMachine.add(new String(""+arr[i]));
            }
        }
        
        timeMachine = new Point[arrayMachine.size()];
        for(int i=0; i<timeMachine.length; i++){
            timeMachine[i] = new Point(Integer.parseInt(arrayMachine.get(i)),0);
        }
    }
    
    public void delMachine(int truckCap){
        if (arrayMachine.size()<truckCap){
            for (int i=0; i<=arrayMachine.size(); i++)
                arrayMachine.removeFirst();
        } else {
            for (int i=0; i<truckCap; i++)
                arrayMachine.removeFirst();
        }
    }
    
    public boolean isSameChar (String str, char c){
        boolean found = false;
        for(int i=0; i<str.length(); i++){
            if(str.charAt(i)==c){
                found = true;
                break;
            }
        }
        return found;
    }
    
    public String[] getTupleOfListNameVendor(int truckCap){
        String[] tupleFinal;
        String[] tuple;
        //make static tuple of list name vendor for each machine
        if (arrayMachine.size()<truckCap){
            tuple = new String[arrayMachine.size()];
            for (int i=0; i<arrayMachine.size(); i++){
                tuple[i] = VendorList.getListNameVendor(Integer.valueOf(arrayMachine.get(i)));
            }
        } else {
            tuple = new String[truckCap];
            for (int i=0; i<truckCap; i++){
                tuple[i] = VendorList.getListNameVendor(Integer.valueOf(arrayMachine.get(i)));
            }
        }
        //for(int i=0; i<tuple.length; i++){
            //System.out.println("vendor utk mesin["+(i+1)+"] "+tuple[i]);
        //}
        
        //delete machine
        delMachine(truckCap);
        
        //make final tuple of list name vendor        
        //cari jumlah tuplefinalnya
        int n=1;
        for(int i=0; i<tuple.length; i++){
            n=n*tuple[i].length();
        }
        
        tupleFinal = new String[n];
        //masukin satu persatu
        int divider = 1;
        for(int i=0; i<tuple.length; i++){
            for(int l=0; l<divider; l++){
                for(int j=0; j<tuple[i].length(); j++){
                    for(int k=0; k<n/tuple[i].length(); k++){
                        //System.out.println("i "+i+" -> "+((l*n)+(j*n/tuple[i].length())+k)+" -> "+tuple[i].charAt(j));
                        if (i==0){
                            tupleFinal[(l*n)+(j*n/tuple[i].length())+k] = ""+tuple[i].charAt(j);
                        } else {
                            if (!isSameChar(tupleFinal[(l*n)+(j*n/tuple[i].length())+k],tuple[i].charAt(j)))
                                tupleFinal[(l*n)+(j*n/tuple[i].length())+k] = tupleFinal[(l*n)+(j*n/tuple[i].length())+k] + tuple[i].charAt(j);
                        }
                    }
                }
            }
            divider = divider * tuple[i].length(); //update divider
            n = n / tuple[i].length(); //update n
        }
    
        return tupleFinal;
    }

    public int minPath(int[] arr){
        int min = 0;
        for(int i=0;i<arr.length;i++){
            if (arr[i]<min){
                min = arr[i];
            }
        }
        return min;
    }
    
    public Point[] getListPoint (String str){
        Point[] listPoint = new Point[str.length()+2];
        listPoint[0] = new Point(Map.posPabrik);
        for (int i=0; i<str.length(); i++){
            listPoint[i+1] = new Point(VendorList.getPosVendor(new String (""+str.charAt(i))));
        }
        listPoint[listPoint.length-1] = new Point(Map.posPabrik);
        return listPoint;
    }
    
    public int getValue (Point[] listPoint){
        int value = 0;
        for(int i=0; i<listPoint.length-1; i++){
            //System.out.println("start "+listPoint[i].x+","+listPoint[i].y+" target "+listPoint[i+1].x+","+listPoint[i].y);
            finding(listPoint[i],listPoint[i+1]);
            value = value + Path.size();
            Path.removeAll(Path);
        }
        return value;
    }
    
    public int getIdxMin(int[] arr){
        int min=arr[0];
        int idx=0;
        for(int i=1; i<arr.length; i++){
            if(arr[i]<min){
                min=arr[i];
                idx=i;
            }
        }
        return idx;
    }
    
    public void process(int truckCap, int[] arr){
        int[] listValue;
        String[] tuple;
        int idxMin=0;
        Point[] listPointFix;
        int it=0;
        int count = 0;

        setArrayMachine(arr);
        while(!arrayMachine.isEmpty()){
            tuple = getTupleOfListNameVendor(truckCap);
            for(int i=0; i<tuple.length; i++){
                //System.out.println("tuple["+i+"] "+tuple[i]);
            }
            
            listValue = new int[tuple.length];
            for(int i=0; i<listValue.length; i++){
                listValue[i] = getValue(getListPoint(tuple[i]));
                //System.out.println("value["+i+"] "+listValue[i]);
            }
            idxMin = getIdxMin(listValue);
            //System.out.println("IDXMIN "+idxMin);
            
            if ((it+1)*truckCap>timeMachine.length){
                for(int i=(it*truckCap); i<timeMachine.length; i++){
                    timeMachine[i].y = listValue[idxMin]+count;
                }
            } else {
                for(int i=(it*truckCap); i<((it+1)*truckCap); i++){
                    timeMachine[i].y = listValue[idxMin]+count;
                }
            }
            count = count+listValue[idxMin];
            
            listPointFix = getListPoint(tuple[idxMin]);
            for(int i=0; i<listPointFix.length-1; i++){
                finding(listPointFix[i],listPointFix[i+1]);
                finalPath.addAll(Path);
                Path.removeAll(Path);                
            }
            
            it++;
        }
    }
    
    public static void main(String[] args){
        Parser.parse("input5x5.txt");
        int arr[] = {1,2,3,3,3,5,1,1,1,5,1,4,4,4,4,2,2,2,2,2,2,2};
        PathFinding PF = new PathFinding(1);
        PF.process(2, arr);
        for(int i=0; i<PF.finalPath.size(); i++){
            //System.out.println("FINALPATH["+i+"] "+PF.finalPath.get(i).x+","+PF.finalPath.get(i).y);
        }
        
//        String[] T = PF.getTupleOfListNameVendor(3);
//        for(int i=0; i<T.length; i++)
//            System.out.println(T[i]);

//        PF.setArrayMachine(arr);
//        for (int i=0; i<PF.arrayMachine.size(); i++){
//            System.out.println(PF.arrayMachine.get(i));
//        }  
//
//        for (int i=0; i<PF.arrayMachine.size(); i++){
//            System.out.println(PF.arrayMachine.get(i));
//        }  
//        
//        Point[] listP = PF.getListPoint("AB");
//        for (int i=0; i<listP.length; i++){
//            System.out.println(listP[i].x+","+listP[i].y);
//        }
//        
//        int val = PF.getValue(listP);
//        System.out.println("value "+val);
    }
}
